﻿package com.riaidea.text {
    import flash.text.*;
    import flash.display.*;
    import flash.utils.*;
    import flash.geom.*;
    import flash.events.*;
    import com.riaidea.text.plugins.*;

    public class RichTextField extends Sprite {

        public static const DYNAMIC:String = "dynamic";
        public static const INPUT:String = "input";
        public static const version:String = "2.0.2";

        private static var _countenance:Object = {};

        private var _width:Number;
        private var _height:Number;
        private var _textRenderer:TextRenderer;
        private var _spriteRenderer:SpriteRenderer;
        private var _formatCalculator:TextField;
        private var _plugins:Array;
        private var _placeholder:String;
        private var _placeholderColor:uint;
        private var _placeholderMarginH:int;
        private var _placeholderMarginV:int;
        public var html:Boolean;
        public var lineHeight:int;
        public var autoScroll:Boolean;

        public function RichTextField(){
            this._textRenderer = new TextRenderer();
            addChild(this._textRenderer);
            this._spriteRenderer = new SpriteRenderer(this);
            addChild(this._spriteRenderer.container);
            this.setSize(100, 100);
            this.type = DYNAMIC;
            this.lineHeight = 0;
            this.html = false;
            this.autoScroll = false;
            this._placeholder = String.fromCharCode(0x3000);
            this._placeholderColor = 0;
            this._placeholderMarginH = 1;
            this._placeholderMarginV = 0;
            this._formatCalculator = new TextField();
            this._formatCalculator.text = this._placeholder;
            this._textRenderer.restrict = ("^" + this._placeholder);
        }
        public static function addCountenance(_arg1:String, _arg2:Class):void{
            _countenance[_arg1] = _arg2;
        }

        public function append(_arg1:String, _arg2:Array=null, _arg3:Boolean=false, _arg4:TextFormat=null):void{
            var _local5:int = this._textRenderer.scrollV;
            var _local6:int = this._textRenderer.length;
            var _local7:int;
            if (!(_arg1)){
                _arg1 = "";
            };
            if (((_arg1) || (_arg3))){
                if (_arg1){
                    _arg1 = _arg1.split("\r").join("\n");
                };
                if (((_arg3) && (!(this.html)))){
                    _arg1 = (_arg1 + "\n");
                };
                this._textRenderer.recoverDefaultFormat();
                if (this.html){
                    this._textRenderer.htmlText = (this._textRenderer.htmlText + (("<p>" + _arg1) + "</p>"));
                } else {
                    this._textRenderer.appendText(_arg1);
                    if (_arg4 == null){
                        _arg4 = this._textRenderer.defaultTextFormat;
                    };
                    this._textRenderer.setTextFormat(_arg4, _local6, this._textRenderer.length);
                };
                if (((this.html) || (((_arg3) && (!(this.html)))))){
                    _local7 = ((this._textRenderer.length - _local6) - 1);
                } else {
                    _local7 = (this._textRenderer.length - _local6);
                };
            };
            var _local8:Boolean = ((this.html) && (!((_local6 == 0))));
            this.insertSprites(_arg2, _local6, (_local6 + _local7), _local8);
            if (((this.autoScroll) && (!((this._textRenderer.scrollV == this._textRenderer.maxScrollV))))){
                this._textRenderer.scrollV = this._textRenderer.maxScrollV;
            } else {
                if (((!(this.autoScroll)) && (!((this._textRenderer.scrollV == _local5))))){
                    this._textRenderer.scrollV = _local5;
                };
            };
            if (_arg2 != null){
                this._spriteRenderer.render();
            };
        }
        public function replace(_arg1:int, _arg2:int, _arg3:String, _arg4:Array=null):void{
            var _local5:int = this._textRenderer.length;
            var _local6:int;
            if (_arg2 > _local5){
                _arg2 = _local5;
            };
            _arg3 = _arg3.split(this._placeholder).join("");
            this._textRenderer.replaceText(_arg1, _arg2, _arg3);
            _local6 = ((this._textRenderer.length - _local5) + (_arg2 - _arg1));
            if (_local6 > 0){
                this._textRenderer.setTextFormat(this._textRenderer.defaultTextFormat, _arg1, (_arg1 + _local6));
            };
            var _local7:int = _arg1;
            while (_local7 < _arg2) {
                this._spriteRenderer.removeSprite(_local7);
                _local7++;
            };
            var _local8:Boolean = this._spriteRenderer.adjustSpritesIndex((_arg1 - 1), (this._textRenderer.length - _local5));
            this.insertSprites(_arg4, _arg1, (_arg1 + _local6));
            if (((_local8) || (((_arg4) && ((_arg4.length > 0)))))){
                this._spriteRenderer.render();
            };
        }
        private function insertSprites(_arg1:Array, _arg2:int, _arg3:int, _arg4:Boolean=false):void{
            var _local6:Object;
            var _local7:Object;
            var _local8:int;
            if (_arg1 == null){
                return;
            };
            _arg1.sortOn("index", Array.NUMERIC);
            var _local5:int;
            while (_local5 < _arg1.length) {
                _local6 = _arg1[_local5];
                _local7 = _local6.src;
                _local8 = _local6.index;
                if ((((((_local6.index == undefined)) || ((_local8 < 0)))) || ((_local8 > (_arg3 - _arg2))))){
                    _local6.index = (_arg3 - _arg2);
                    _arg1.splice(_local5, 1);
                    _arg1.push(_local6);
                    _local5--;
                } else {
                    if (((((_arg4) && ((_local8 > 0)))) && ((_local8 < (_arg3 - _arg2))))){
                        _local8 = (_local8 + ((_arg2 + _local5) - 1));
                    } else {
                        _local8 = (_local8 + (_arg2 + _local5));
                    };
                    this.insertSprite(_local7, _local8, false, _local6.cache);
                };
                _local5++;
            };
        }
        public function insertSprite(_arg1:Object, _arg2:int=-1, _arg3:Boolean=true, _arg4:Boolean=false):void{
            var _local7:Number;
            var _local5:DisplayObject = this.getSpriteFromObject(_arg1);
            if (_local5 == null){
                throw (Error((("Specific sprite:" + _arg1) + " is not a valid display object!")));
            };
            if (_arg4){
                _local5.cacheAsBitmap = true;
            };
            if ((((this.lineHeight > 0)) && ((_local5.height > this.lineHeight)))){
                _local7 = (this.lineHeight / _local5.height);
                _local5.height = this.lineHeight;
                _local5.width = (_local5.width * _local7);
            };
            if ((((_arg2 < 0)) || ((_arg2 > this._textRenderer.length)))){
                _arg2 = this._textRenderer.length;
            };
            this._textRenderer.replaceText(_arg2, _arg2, this._placeholder);
            var _local6:TextFormat = this.calcPlaceholderFormat(_local5.width, _local5.height);
            this._textRenderer.setTextFormat(_local6, _arg2, (_arg2 + 1));
            this._spriteRenderer.adjustSpritesIndex(_arg2, 1);
            this._spriteRenderer.insertSprite(_local5, _arg2);
            if (_arg3){
                this._spriteRenderer.render();
            };
        }
        private function getSpriteFromObject(_arg1:Object):DisplayObject{
            var _local2:Class;
            var _local3:Class;
            if ((_arg1 is String)){
                _local3 = RichTextField._countenance[_arg1];
                if (_local3){
                    _local2 = _local3;
                } else {
                    _local2 = (getDefinitionByName(String(_arg1)) as Class);
                };
                return ((new (_local2)() as DisplayObject));
            };
            if ((_arg1 is Class)){
                return ((new (_arg1)() as DisplayObject));
            };
            return ((_arg1 as DisplayObject));
        }
        private function calcPlaceholderFormat(_arg1:Number, _arg2:Number):TextFormat{
            var _local3:TextFormat = new TextFormat();
            _local3.color = this._placeholderColor;
            _local3.size = (_arg2 + (2 * this._placeholderMarginV));
            this._formatCalculator.setTextFormat(_local3);
            var _local4:TextLineMetrics = this._formatCalculator.getLineMetrics(0);
            _local3.letterSpacing = ((_arg1 - _local4.width) + (2 * this._placeholderMarginH));
            _local3.underline = (_local3.italic = (_local3.bold = false));
            return (_local3);
        }
        public function setSize(_arg1:Number, _arg2:Number):void{
            if ((((this._width == _arg1)) && ((this._height == _arg2)))){
                return;
            };
            this._width = _arg1;
            this._height = _arg2;
            this._textRenderer.width = this._width;
            this._textRenderer.height = this._height;
            this.scrollRect = new Rectangle(0, 0, this._width, this._height);
            this._spriteRenderer.render();
        }
        public function isSpriteAt(_arg1:int):Boolean{
            if ((((_arg1 < 0)) || ((_arg1 >= this._textRenderer.length)))){
                return (false);
            };
            return ((this._textRenderer.text.charAt(_arg1) == this._placeholder));
        }
        private function scrollHandler(_arg1:Event):void{
            this._spriteRenderer.render();
        }
        private function changeHandler(_arg1:Event):void{
            var _local4:int;
            var _local2:int = this._textRenderer.caretIndex;
            var _local3:int = (this._textRenderer.length - this._textRenderer.oldLength);
            if (_local3 > 0){
                this._spriteRenderer.adjustSpritesIndex((_local2 - 1), _local3);
            } else {
                _local4 = _local2;
                while (_local4 < (_local2 - _local3)) {
                    this._spriteRenderer.removeSprite(_local4);
                    _local4++;
                };
                this._spriteRenderer.adjustSpritesIndex((_local2 + _local3), _local3);
            };
            this._spriteRenderer.render();
        }
        public function clear():void{
            this._spriteRenderer.clear();
            this._textRenderer.clear();
        }
        public function get type():String{
            return (this._textRenderer.type);
        }
        public function set type(_arg1:String):void{
            this._textRenderer.type = _arg1;
            this._textRenderer.addEventListener(Event.SCROLL, this.scrollHandler);
            if (_arg1 == INPUT){
                this._textRenderer.addEventListener(Event.CHANGE, this.changeHandler);
            };
        }
        public function get textfield():TextField{
            return (this._textRenderer);
        }
        public function set placeholderMarginH(_arg1:int):void{
            this._placeholderMarginH = _arg1;
        }
        public function set placeholderMarginV(_arg1:int):void{
            this._placeholderMarginV = _arg1;
        }
        public function get viewWidth():Number{
            return (this._width);
        }
        public function get viewHeight():Number{
            return (this._height);
        }
        public function get content():String{
            return (this._textRenderer.text);
        }
        public function get contentLength():int{
            return (this._textRenderer.length);
        }
        public function get text():String{
            return (this._textRenderer.text.split(this._placeholder).join(""));
        }
        public function get textLength():int{
            return ((this._textRenderer.length - this._spriteRenderer.numSprites));
        }
        public function getSprite(_arg1:int):DisplayObject{
            return (this._spriteRenderer.getSprite(_arg1));
        }
        public function get numSprites():int{
            return (this._spriteRenderer.numSprites);
        }
        public function get caretIndex():int{
            return (this._textRenderer.caretIndex);
        }
        public function set caretIndex(_arg1:int):void{
            this._textRenderer.setSelection(_arg1, _arg1);
        }
        public function get defaultTextFormat():TextFormat{
            return (this._textRenderer.defaultTextFormat);
        }
        public function set defaultTextFormat(_arg1:TextFormat):void{
            if (_arg1.color != null){
                this._placeholderColor = uint(_arg1.color);
            };
            this._textRenderer.defaultTextFormat = _arg1;
        }
        public function exportXML():XML{
            var _local1:XML = <rtf/>
            ;
            if (this.html){
                _local1.htmlText = this._textRenderer.htmlText.split(this._placeholder).join("");
            } else {
                _local1.text = this._textRenderer.text.split(this._placeholder).join("");
            };
            _local1.sprites = this._spriteRenderer.exportXML();
            return (_local1);
        }
        public function importXML(_arg1:XML):void{
            var _local5:XML;
            var _local6:Object;
            var _local7:int;
            var _local2:String = "";
            if (_arg1.hasOwnProperty("htmlText")){
                _local2 = (_local2 + _arg1.htmlText);
            };
            if (_arg1.hasOwnProperty("text")){
                _local2 = (_local2 + _arg1.text);
            };
            var _local3:Array = [];
            var _local4:int;
            while (_local4 < _arg1.sprites.sprite.length()) {
                _local5 = _arg1.sprites.sprite[_local4];
                _local6 = {};
                _local6.src = String(_local5.@src);
                _local7 = int(_local5.@index);
                if (((((this.html) && ((this.contentLength > 0)))) && ((_local7 > 0)))){
                    _local6.index = (_local7 + 1);
                } else {
                    _local6.index = _local7;
                };
                _local3.push(_local6);
                _local4++;
            };
            this.append(_local2, _local3);
        }
        public function addPlugin(_arg1:IRTFPlugin):void{
            _arg1.setup(this);
            if (this._plugins == null){
                this._plugins = [];
            };
            this._plugins.push(_arg1);
        }

    }
}//package com.riaidea.text 
